/*
 * @(#)MaintWorkflowTaskAction.java
 *
 * Copyright (c) 2003 DCIVision Ltd
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of DCIVision
 * Ltd ("Confidential Information").  You shall not disclose such Confidential
 * Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with DCIVision Ltd.
 */
package com.dcivision.workflow.web;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.impl.LogFactoryImpl;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.upload.FormFile;

import com.dcivision.alert.bean.UpdateAlertLogAction;
import com.dcivision.alert.core.AlertManager;
import com.dcivision.dms.DmsOperationConstant;
import com.dcivision.dms.bean.DmsDocument;
import com.dcivision.dms.core.DocumentOperationManager;
import com.dcivision.dms.core.DocumentRetrievalManager;
import com.dcivision.dms.core.DocumentValidateManager;
import com.dcivision.dms.dao.DmsDocumentDAObject;
import com.dcivision.form.bean.FormSubmission;
import com.dcivision.form.dao.FormSubmissionDAObject;
import com.dcivision.framework.ApplicationException;
import com.dcivision.framework.ErrorConstant;
import com.dcivision.framework.GlobalConstant;
import com.dcivision.framework.MessageResourcesFactory;
import com.dcivision.framework.SessionContainer;
import com.dcivision.framework.SystemFunctionConstant;
import com.dcivision.framework.SystemParameterConstant;
import com.dcivision.framework.SystemParameterFactory;
import com.dcivision.framework.TextUtility;
import com.dcivision.framework.UserInfoFactory;
import com.dcivision.framework.Utility;
import com.dcivision.framework.web.AbstractActionForm;
import com.dcivision.framework.web.AbstractMaintAction;
import com.dcivision.framework.web.AbstractSearchForm;
import com.dcivision.workflow.WorkflowOperationConstant;
import com.dcivision.workflow.bean.MtmWorkflowProgressSystemObject;
import com.dcivision.workflow.bean.MtmWorkflowProgressUserRecord;
import com.dcivision.workflow.bean.MtmWorkflowStepUserActor;
import com.dcivision.workflow.bean.MtmWorkflowStepWorkflowStep;
import com.dcivision.workflow.bean.WorkflowGroup;
import com.dcivision.workflow.bean.WorkflowProgress;
import com.dcivision.workflow.bean.WorkflowProgressAttachment;
import com.dcivision.workflow.bean.WorkflowRecord;
import com.dcivision.workflow.bean.WorkflowStep;
import com.dcivision.workflow.bean.WorkflowStepRoute;
import com.dcivision.workflow.core.SystemWorkflowConstant;
import com.dcivision.workflow.core.WorkflowPermissionManager;
import com.dcivision.workflow.core.WorkflowProgressManager;
import com.dcivision.workflow.core.WorkflowRetrievalManager;
import com.dcivision.workflow.dao.MtmWorkflowChildParentProgressDAObject;
import com.dcivision.workflow.dao.MtmWorkflowDynamicUserActorDAObject;
import com.dcivision.workflow.dao.MtmWorkflowProgressNotifyRuleDAObject;
import com.dcivision.workflow.dao.MtmWorkflowProgressSystemObjectDAObject;
import com.dcivision.workflow.dao.MtmWorkflowProgressUserRecordDAObject;
import com.dcivision.workflow.dao.MtmWorkflowStepWorkflowStepDAObject;
import com.dcivision.workflow.dao.WorkflowGroupDAObject;
import com.dcivision.workflow.dao.WorkflowProgressAttachmentDAObject;
import com.dcivision.workflow.dao.WorkflowProgressDAObject;
import com.dcivision.workflow.dao.WorkflowRecordDAObject;
import com.dcivision.workflow.dao.WorkflowStepDAObject;
import com.dcivision.workflow.dao.WorkflowStepRouteDAObject;

/**
 MaintWorkflowTaskAction.java
 
 This class is for maint wprkflow record.
 
 @author          Angus Shiu
 @company         DCIVision Limited
 @creation date   29/07/2003
 @version         $Revision: 1.106.2.2 $
 */
public class MaintWorkflowTaskAction extends AbstractMaintAction {
  
  
  public static final String REVISION = "$Revision: 1.106.2.2 $";
  protected Log logger = new LogFactoryImpl().getInstance(this.getClass());
  
  /** Creates a new instance of MaintWorkflowTaskAction */
  public MaintWorkflowTaskAction() {
    super();
  }
  
  /** getFunctionCode
   *
   * Abstract function which sub-class should implement to return the corresponding
   * function code.
   *
   * @return   The function code
   */
  public String getFunctionCode() {
    return(SystemFunctionConstant.WORKFLOW_TASK);
  }
  
  /** getMajorDAOClassName
   *
   * Abstract function which sub-class should implement to return the corresponding
   * major DAO class name used in this class.
   *
   * @return   The DAO class name
   */
  public String getMajorDAOClassName() {
    return("com.dcivision.workflow.dao.WorkflowProgressDAObject");
  }
  
  public void clearUniqueFields(ActionMapping mapping, AbstractActionForm form, HttpServletRequest request, HttpServletResponse response) throws ApplicationException {
    MaintWorkflowProgressForm workflowProgressForm = (MaintWorkflowProgressForm) form;
    workflowProgressForm.setID(null);
  }
  
  public void updateRecord(ActionMapping mapping,
      AbstractActionForm form,
      HttpServletRequest request,
      HttpServletResponse response)
  throws ApplicationException {
    SessionContainer sessionCon = this.getSessionContainer(request);
    Connection conn = this.getConnection(request);
    WorkflowProgressManager progressManager = new WorkflowProgressManager(sessionCon, conn);
    MaintWorkflowProgressForm maintForm = (MaintWorkflowProgressForm) form;
    Boolean proceedToNextProgress = new Boolean(false);
    
    //* prepare the list of workflow attachment
    if ( !Utility.isEmpty(maintForm.getFileNames()) ) {
      com.dcivision.upload.core.MultipleFileUploadUtil uploadUtil = new com.dcivision.upload.core.MultipleFileUploadUtil(sessionCon);
      List attachmentList = uploadUtil.getWorkflowAttachmentList(maintForm.getFileNames(), WorkflowProgressAttachment.ATTACHED_SINGLE_FILE);
      maintForm.setAttachmentList(attachmentList);
    }
    
    if ( !Utility.isEmpty(maintForm.getDmsFileNames()) ) {
      List attachmentList = new ArrayList();
      if (maintForm.getAttachmentList()!=null) {
        attachmentList = maintForm.getAttachmentList();
      }
      if(!Utility.isEmpty(this.getDmsDocumentAttachment(maintForm))){
        attachmentList.addAll(this.getDmsDocumentAttachment(maintForm));
      }
      maintForm.setAttachmentList(attachmentList);
    }
    
    //* check in file
    String storagePath = SystemParameterFactory.getSystemParameter(SystemParameterConstant.WORKFLOW_ATTACHMENT_PHYSICAL_PATH);
    if ( !Utility.isEmpty(maintForm.getSpecialFile()) ) {
      FormFile tmpFile = maintForm.getSpecialFile();
      try {
        if (tmpFile != null) {
          InputStream inputStream = null;
          FileOutputStream fos = null;
          int bufferSize = 8192;
          byte[] buffer = new byte[bufferSize];
          int length = -1;
          
          if (!"".equals(tmpFile.getFileName())) {
            String convertedName = String.valueOf(System.currentTimeMillis());
            String originalName = tmpFile.getFileName();
            
            File convertedFile = new File(storagePath + "/" + convertedName);
            inputStream = tmpFile.getInputStream();
            
            fos = new FileOutputStream(convertedFile);
            while ((length=inputStream.read(buffer, 0, bufferSize)) != -1) {
              fos.write(buffer, 0, length);
            }
            fos.flush();
            inputStream.close();
            fos.close();
            
            inputStream = new FileInputStream(convertedFile);
            WorkflowProgressAttachment attachment = new WorkflowProgressAttachment();
            attachment.setAttachmentName(originalName);
            attachment.setExternalID(convertedName);
            attachment.setFlowType(WorkflowProgressAttachment.ATTACHED_SINGLE_FILE);
            attachment.setDataStream(inputStream);
            attachment.setContentSize(new Integer(""+tmpFile.getFileSize()));
            attachment.setAttachmentType(WorkflowProgressAttachment.ATTACHED_NEW_CHECK_IN_DOCUMENT);
            
            List attachmentList = new ArrayList();
            if (maintForm.getAttachmentList()!=null) {
              attachmentList = maintForm.getAttachmentList();
            }
            attachmentList.add(attachment);
            maintForm.setAttachmentList(attachmentList);
          }
        }
      } catch (Exception e) {
       log.error(e,e);
      }
    }
    
    //* current workflow category is scanning one?
    boolean bIsScanningCategory = false;
    List systemScanningCategory = SystemParameterFactory.getSystemParameterList(SystemParameterConstant.WORKFLOW_SCANNING_CATEGORY);
    WorkflowProgressDAObject progressDAO = new WorkflowProgressDAObject(sessionCon, this.getConnection(request));
    WorkflowProgress workflowProgress = (WorkflowProgress) progressDAO.getObjectByID(TextUtility.parseIntegerObj(maintForm.getID()));
    if (workflowProgress.getSeqNo().intValue() == 2) {
      String wfCategoryID = workflowProgress.getWorkflowCategoryID().toString();
      for (int i = 0; i < systemScanningCategory.size(); i++) {
        String scanningCategory = (String) systemScanningCategory.get(i);
        if (scanningCategory.equals(wfCategoryID)) {
          bIsScanningCategory = true;
          break;
        }
      }
    }
    if (bIsScanningCategory) {
      DocumentOperationManager docOperationManager = new DocumentOperationManager(sessionCon, conn);
      DocumentRetrievalManager docRetrievalManager = new DocumentRetrievalManager(sessionCon, conn);
      MtmWorkflowProgressSystemObjectDAObject progressObjDAO = new MtmWorkflowProgressSystemObjectDAObject(sessionCon, conn);
      
      /**
       * @ToDo To get the MtmWorkflowProgressSystemObject by trackID & objectID
       */
      MtmWorkflowProgressSystemObject progressObj = null;
      List objectList = progressObjDAO.getListByTrackID( TextUtility.parseIntegerObj(request.getParameter("trackID")) );
      if(!Utility.isEmpty(objectList)) {
        progressObj = (MtmWorkflowProgressSystemObject)objectList.get(0); 
      }
      
      //MtmWorkflowProgressSystemObject progressObj = (MtmWorkflowProgressSystemObject) progressObjDAO.getObjectByTrackID(TextUtility.parseIntegerObj(request.getParameter("trackID")));
      Integer scannedDocID = progressObj.getObjectID();
      
      com.dcivision.dms.bean.DmsDocument scannedDocument = docRetrievalManager.getDocument(scannedDocID);
      Integer newRootID = TextUtility.parseIntegerObj(maintForm.getUserDef2());
      //log.debug("new root id: " + newRootID);
      Integer newParentID = TextUtility.parseIntegerObj(maintForm.getUserDef3());
      //log.debug("new parent id: " + newParentID);
      com.dcivision.dms.bean.DmsDocument newParentFolder = docRetrievalManager.getDocument(newParentID);
      //log.debug("has get the new Parent folder");
      docOperationManager.moveDocument(scannedDocument, newParentFolder, newRootID);
    }
    
    com.dcivision.customize.workflow.CustomizationForAction customization = new com.dcivision.customize.workflow.CustomizationForAction();
    customization.workflowTaskCustomization(sessionCon, conn, request, maintForm);
    
    proceedToNextProgress = progressManager.accomplishWorkflowProgressByUser((MaintWorkflowProgressForm)form);
    
    if(WorkflowProgress.FORM_EQUATION_ERROR.equals(progressManager.getAutoRoutedToDefault())){
      this.addMessage(request, MaintWorkflowTaskAction.MESSAGE_FORM_EQUATION_HAS_ERROR);
    } else if (WorkflowProgress.ROUTED_TO_DEFAULT.equals(progressManager.getAutoRoutedToDefault())){
      this.addMessage(request, MaintWorkflowTaskAction.MESSAGE_AUTO_ROUTED_TO_DEFAULT);
    }
    
    // Check next step(s) is check in auto task. and get the check in URL
    if(proceedToNextProgress.booleanValue()){
      if(checkNextStepIsCheckInAutoTask(form,request) ){
        maintForm.setCheckInURL( this.getCheckInURL(form,request));
      }
    }
    
    
    request.setAttribute("assignStepMap", progressManager.getAssignStepMap());
    
    conn = null;
  }
  
  public void selectRecord(ActionMapping mapping, AbstractActionForm form, HttpServletRequest request, HttpServletResponse response) throws ApplicationException {
    // If the task is processed by delegated user, should keep the information after selectRecord
    Integer delegateUserRecordID = ((MaintWorkflowProgressForm)form).getDelegateUserRecordID();
    log.debug ( "delegateUserRecordID = " + ((MaintWorkflowProgressForm)form).getDelegateUserRecordID() );
    super.selectRecord(mapping, form, request, response);
    log.debug ( "delegateUserRecordID = " + ((MaintWorkflowProgressForm)form).getDelegateUserRecordID() );
    if ( delegateUserRecordID != null ) {
      ((MaintWorkflowProgressForm)form).setDelegateUserRecordID(delegateUserRecordID);
    }
    //log.debug ( "delegateUserRecordID = " + ((MaintWorkflowProgressForm)form).getDelegateUserRecordID() );
    
    Connection conn = this.getConnection(request);
    MaintWorkflowProgressForm maintForm = (MaintWorkflowProgressForm) form;
    WorkflowProgress workflowProgress = (WorkflowProgress) maintForm.getFormData();
    
    Map parentStepOptionHasAction = new HashMap();
    String[][] workflowRouteArr = null;
    List checkInWorkflowActionIDList = SystemParameterFactory.getSystemParameterList(SystemParameterConstant.WORKFLOW_DOCUMENT_CHECK_IN_WORKFLOW_ACTION_ID);
  
    // the hashmap store if each possible option for the current step has
    if (WorkflowStep.ACTION_TYPE_APPROVAL.equals(workflowProgress.getActionType())) {
      parentStepOptionHasAction.put(WorkflowStep.PARENT_TYPE_APPROVED, GlobalConstant.FALSE);
      parentStepOptionHasAction.put(WorkflowStep.PARENT_TYPE_REJECTED, GlobalConstant.FALSE);
      
    } else if(WorkflowStep.ACTION_TYPE_BOOLEAN.equals(workflowProgress.getActionType())) {
      parentStepOptionHasAction.put(WorkflowStep.PARENT_TYPE_YES, GlobalConstant.FALSE);
      parentStepOptionHasAction.put(WorkflowStep.PARENT_TYPE_NO, GlobalConstant.FALSE);
      
    } else {
      parentStepOptionHasAction.put(WorkflowStep.PARENT_TYPE_SINGLE, GlobalConstant.FALSE);
    }
    
    SessionContainer sessionCon = this.getSessionContainer(request);
    WorkflowStepDAObject stepDAO = new WorkflowStepDAObject(sessionCon, conn);
    MtmWorkflowStepWorkflowStepDAObject stepStepDAO = new MtmWorkflowStepWorkflowStepDAObject(sessionCon, conn);
    
    boolean bNextStepIsCheckIn = false;
    List childList = stepStepDAO.getListByParentStepID(workflowProgress.getWorkflowStepID());
    int nextStepDueDateCount = 0;
    List dueDateStepList = new ArrayList();
    for (int i=0; i<childList.size(); i++) {
      MtmWorkflowStepWorkflowStep stepStep = (MtmWorkflowStepWorkflowStep) childList.get(i);
      WorkflowStep childStep = (WorkflowStep) stepDAO.getObjectByID(stepStep.getChildStepID());
      
      // get the next step allow assign due date
      if(WorkflowStep.DYNAMIC_ASSIGN_DUE_DATE_TRUE.equals(childStep.getAllowAssignDueDate()) ||
          WorkflowStep.DYNAMIC_ASSIGN_DUE_DATE_MANDATORY.equals(childStep.getAllowAssignDueDate()) ){
        workflowProgress.setNextStepAllowAssignDueDate(childStep.getAllowAssignDueDate());
        maintForm.setNextStepAllowAssignDueDate(childStep.getAllowAssignDueDate());
        dueDateStepList.add(childStep);
        nextStepDueDateCount++;
      }
      
      // if the child step is auto-run step and the auto action is specified by the system parameter, mark the corresponding step option to true
      if (WorkflowStep.ACTION_TYPE_SYSTEM_AUTO.equals(childStep.getActionType())  && checkInWorkflowActionIDList.contains(childStep.getActionID().toString()) ) {
        parentStepOptionHasAction.put(stepStep.getParentType(), GlobalConstant.TRUE);
        bNextStepIsCheckIn = true;
      }
      
      // get the next step's priority allow assign priority rule
      if(GlobalConstant.TRUE.equals(childStep.getAllowAssignPriority())){
        maintForm.setIsAssignPriorityRuleNextStep(true);
      }
    }
    
    maintForm.setNextStepDueDateCount(nextStepDueDateCount);
    request.setAttribute("dueDateStepList", dueDateStepList);
    MtmWorkflowChildParentProgressDAObject childParentDAO = (MtmWorkflowChildParentProgressDAObject) this.getDAObjectByClassName(request, "com.dcivision.workflow.dao.MtmWorkflowChildParentProgressDAObject");
    WorkflowProgressManager progressManager = new WorkflowProgressManager(this.getSessionContainer(request), conn);
    Integer trackID = TextUtility.parseIntegerObj(request.getParameter("trackID"));
    List subworkflowList = childParentDAO.getListByParentTrackID(trackID);
    request.setAttribute("subworkflowList", subworkflowList);
// Commented by Brook.Huang. This operations have done before in method 'execute'.
//    List progressList= progressManager.getWorkflowProgressList(workflowProgress.getTrackID());
//    List attachmentList = new ArrayList();
//    for (int i=0; i<progressList.size(); i++) {
//      WorkflowProgress progress = (WorkflowProgress) progressList.get(i);
//      attachmentList.addAll(progressManager.getWorkflowProgressAttachmentList(progress.getID()));
//    }
//    request.setAttribute("attachmentList", attachmentList);
    
    //* current workflow category is scanning one?
    boolean bIsScanningCategory = false;
    List systemScanningCategory = SystemParameterFactory.getSystemParameterList(SystemParameterConstant.WORKFLOW_SCANNING_CATEGORY);
    WorkflowProgressDAObject progressDAO = new WorkflowProgressDAObject(sessionCon, conn);
    workflowProgress = (WorkflowProgress) progressDAO.getObjectByID(workflowProgress.getID());
    if (workflowProgress.getSeqNo().intValue() == 2) {
      String wfCategoryID = workflowProgress.getWorkflowCategoryID().toString();
      for (int i = 0; i < systemScanningCategory.size(); i++) {
        String scanningCategory = (String) systemScanningCategory.get(i);
        if (scanningCategory.equals(wfCategoryID)) {
          bIsScanningCategory = true;
          break;
        }
      }
    }
    
    // get possible decision
    if (WorkflowStep.ACTION_TYPE_USER_DEFINED_TASK.equals(workflowProgress.getActionType())) {
      WorkflowStepRouteDAObject stepRouteDAO = new WorkflowStepRouteDAObject(sessionCon, conn);
      log.debug("workflow step id, getting workflow routes: "+workflowProgress.getWorkflowStepID());
      List tmpList = stepRouteDAO.getListByWorkflowStepID(workflowProgress.getWorkflowStepID());
      workflowRouteArr = new String[tmpList.size()+1][];
      workflowRouteArr[0] = new String[] {MessageResourcesFactory.getMessage(sessionCon.getSessionLocale(), "common.options.select_menu.select_one"), ""};
      for (int i=0; i<tmpList.size(); i++) {
        WorkflowStepRoute stepRoute = (WorkflowStepRoute) tmpList.get(i);
        workflowRouteArr[1+i] = new String[] {stepRoute.getRouteName(), WorkflowStep.PARENT_TYPE_SINGLE + stepRoute.getRouteSeq()};
      }
    }
    
    //get the checkout user and check the checkout progress by current user
    
    //added by nancy
    

    WorkflowProgress currentWFprogress = progressManager.getWorkflowProgress(TextUtility.parseIntegerObj(maintForm.getID()));
    MtmWorkflowProgressUserRecordDAObject mtmProgressUserDAO = new MtmWorkflowProgressUserRecordDAObject(sessionCon, this.getConnection(request));
    List completeUserIDList =  mtmProgressUserDAO.getCompletedUserProcessRecordByWorkflowProgressID(workflowProgress.getID());
    WorkflowStep sfStep=(WorkflowStep)stepDAO.getObjectByID(currentWFprogress.getWorkflowStepID());
    boolean isCompleteUser=false;
    for(int i=0;i<completeUserIDList.size();i++){
      if( sessionCon.getUserRecordID().equals(((MtmWorkflowProgressUserRecord)completeUserIDList.get(i)).getUserRecordID())){
        isCompleteUser=true;
        break;
      }
    }
    int workflowRule=0;
    MtmWorkflowDynamicUserActorDAObject dynamicUserDAO = new MtmWorkflowDynamicUserActorDAObject(sessionCon, conn);
    WorkflowRetrievalManager wfRetrievalManager = new WorkflowRetrievalManager(sessionCon, conn);
    if("*".equals(sfStep.getWorkflowRule())){
      List assignedUserList = null;
      log.debug("currentStep.getActorType()="+sfStep.getActorType());
      if (MtmWorkflowStepUserActor.ACTOR_TYPE_RECURSIVE_RUNTIME_ASSIGN.equals(sfStep.getAssignActorType())
          || MtmWorkflowStepUserActor.ACTOR_TYPE_RUNTIME_ASSIGN.equals(sfStep.getAssignActorType()) ){
        assignedUserList = dynamicUserDAO.getDynamicUserIDListByWorkflowProgressID(currentWFprogress.getID());
      } else {
        assignedUserList = wfRetrievalManager.getUserListForStepAssignment(sfStep.getID());
      }
      workflowRule = assignedUserList.size();
    } else {
      workflowRule = TextUtility.parseInteger(sfStep.getWorkflowRule());
    }
    if(((WorkflowProgress.STATUS_PENDING).equals(currentWFprogress.getStatus())
        ||(WorkflowProgress.STATUS_IN_PROGRESS).equals(currentWFprogress.getStatus()))
        &&(completeUserIDList.size() < workflowRule
            && !isCompleteUser)){
    List checkoutUserIDList =  mtmProgressUserDAO.getCheckoutUserIDListByWorkflowProgressID(workflowProgress.getID().toString());
    String checkoutUserFullName = "";
    for (int j=0; j< checkoutUserIDList.size(); j++){
      if(sessionCon.getUserRecordID().equals(checkoutUserIDList.get(j) )){
        maintForm.setCheckOut(true);
      }
      if(j > 0){
        checkoutUserFullName += ", ";
      }
      checkoutUserFullName += UserInfoFactory.getUserFullName((Integer)checkoutUserIDList.get(j) );
    }
    
    if(!Utility.isEmpty(checkoutUserFullName)){ 
      addMessage(request,"workflow.message.peckedup_task",checkoutUserFullName);
    }
    }else{
      String completeUserFullName = "";
      for (int j=0; j< completeUserIDList.size(); j++){
        if(j > 0){
          completeUserFullName += ", ";
        }
        completeUserFullName += UserInfoFactory.getUserFullName(((MtmWorkflowProgressUserRecord)completeUserIDList.get(j)).getUserRecordID() );
      }
      if(!Utility.isEmpty(completeUserFullName)){
        addMessage(request,"workflow.message.complete_task",completeUserFullName);
      }
      request.setAttribute("isCompleteUser",new Boolean(isCompleteUser));
    }

    //log.debug("parent step option has action map: "+parentStepOptionHasAction);
    request.setAttribute("stepOptionHasActionMap", parentStepOptionHasAction);
    request.setAttribute("nextStepIsCheckIn", new Boolean(bNextStepIsCheckIn));
    request.setAttribute("scanningCategory", new Boolean(bIsScanningCategory));
    request.setAttribute("workflowRouteList", workflowRouteArr);
  }
  /**
   * 
   * @param request
   * @param systemLogID
   * @throws ApplicationException
   */
  private void setSystemLogToRead(HttpServletRequest request,Integer systemLogID)
      throws ApplicationException {
    Connection conn = this.getConnection(request);
    AlertManager alertManager = new AlertManager(this.getSessionContainer(request), conn);

    if (!alertManager.checkForSystemLogActionByActionType(systemLogID,
        UpdateAlertLogAction.READ_ACTION)) {
      alertManager.createSystemLogAction(systemLogID, UpdateAlertLogAction.READ_ACTION, null);
    }

    try {
      conn.commit();
    }
    catch (SQLException e) {
      log.error(e, e);
    }

  }  
  
  public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws ServletException { 
	  String list=request.getParameter("listType");
	  if(!Utility.isEmpty(list)){
		  request.setAttribute("list", list);
	  }
    //add by greatwall 2006-12-20 for eip-849
    if(!Utility.isEmpty(request.getParameter("isFromMessageManager"))){
      
      String systemLogID = request.getParameter("systemLogID");
      if (!Utility.isEmpty(systemLogID)) {
        setSystemLogToRead(request,TextUtility.parseIntegerObj(systemLogID));
      }
    }
    //add by greatwall 2006-12-20 for eip-849
	  //sliever.hu.add
   MaintWorkflowProgressForm maintForm = (MaintWorkflowProgressForm) form;
   //king---add----start
   if(request.getParameter("decisionView")!=null){
	  	request.setAttribute("decisionvalue", request.getParameter("decisionView"));
	  	WorkflowStepRouteDAObject stepRouteDAO = new WorkflowStepRouteDAObject(this.getSessionContainer(request),this.getConnection(request));
       List tmpList = stepRouteDAO.getListByWorkflowStepID(Integer.valueOf(maintForm.getWorkflowStepID()));
       if(tmpList!=null){
       	for (int i=0; i<tmpList.size(); i++) {
       		WorkflowStepRoute stepRoute = (WorkflowStepRoute) tmpList.get(i);
       		if(stepRoute.getRouteName().equals(request.getParameter("decisionView"))){
       			maintForm.setDecision(new String[]{stepRoute.getRouteName(), WorkflowStep.PARENT_TYPE_SINGLE + stepRoute.getRouteSeq()});
       		}
       	}
       }	  	
	  }
   //king----add----end
   WorkflowProgress workflowProgress = (WorkflowProgress) maintForm.getFormData();
  // * get user comment
  SessionContainer sessionCon = this.getSessionContainer(request);
  Connection dbConn = this.getConnection(request);
  String currentRoute = null;
  Integer WorkflowProgessId = null;
  String currentComment = null;
  currentComment = maintForm.getReason();
  String opMode = (maintForm!=null) ? maintForm.getOpMode() : request.getParameter("opMode");    //maintForm.getOpMode();
  String navMode = (maintForm!=null) ? maintForm.getNavMode() : request.getParameter("navMode"); //maintForm.getNavMode();

  //simon_add_start
  Connection conn = this.getConnection(request);
  SessionContainer sessionContainer = (SessionContainer) request.getSession().getAttribute(GlobalConstant.SESSION_CONTAINER_KEY);
  
  // falcon_add_start
  WorkflowProgressDAObject progressDAO=new WorkflowProgressDAObject(this.getSessionContainer(request),this.getConnection(request));
  WorkflowStepDAObject wfstepDAO=new WorkflowStepDAObject(this.getSessionContainer(request),this.getConnection(request));
  WorkflowProgress tempProgress=(WorkflowProgress)progressDAO.getObjectByID(new Integer(maintForm.getID()));
  WorkflowStep step2=(WorkflowStep)wfstepDAO.getObjectByID(tempProgress.getWorkflowStepID());
  maintForm.setWorkflowRecordID(step2.getWorkflowRecordID().toString());
  // falcon_add_end
  
  String workflowRecordID=maintForm.getWorkflowRecordID();
  WorkflowRecordDAObject WorkflowRecordDAObject = new WorkflowRecordDAObject(this.getSessionContainer(request), this.getConnection(request));
  WorkflowRecord currentRecord = (WorkflowRecord) WorkflowRecordDAObject.getObjectByID(new Integer(workflowRecordID));
  WorkflowGroupDAObject wfGroupDAO = new WorkflowGroupDAObject(sessionContainer, conn);
  WorkflowGroup wfGroup = (WorkflowGroup) wfGroupDAO.getObjectByID(currentRecord.getWorkflowGroupID());
  request.setAttribute("workflowGroup", wfGroup);
  //simon_add_end
  //added by nancy
  WorkflowProgressManager progressManager = new WorkflowProgressManager(sessionCon, dbConn);
  WorkflowProgress currentWFprogress = progressManager.getWorkflowProgress(TextUtility.parseIntegerObj(maintForm.getID()));
  
  
  int workflowRule=0;
  WorkflowStepDAObject stepDAO = new WorkflowStepDAObject(sessionCon, this.getConnection(request));
  MtmWorkflowDynamicUserActorDAObject dynamicUserDAO = new MtmWorkflowDynamicUserActorDAObject(sessionCon, this.getConnection(request));
  WorkflowRetrievalManager wfRetrievalManager = new WorkflowRetrievalManager(sessionCon, this.getConnection(request));
  WorkflowStep sfStep=(WorkflowStep)stepDAO.getObjectByID(currentWFprogress.getWorkflowStepID());
  
  if("*".equals(sfStep.getWorkflowRule())){
    List assignedUserList = null;
    log.debug("currentStep.getActorType()="+sfStep.getActorType());
    if (MtmWorkflowStepUserActor.ACTOR_TYPE_RECURSIVE_RUNTIME_ASSIGN.equals(sfStep.getAssignActorType())
        || MtmWorkflowStepUserActor.ACTOR_TYPE_RUNTIME_ASSIGN.equals(sfStep.getAssignActorType()) ){
      assignedUserList = dynamicUserDAO.getDynamicUserIDListByWorkflowProgressID(currentWFprogress.getID());
    } else {
      assignedUserList = wfRetrievalManager.getUserListForStepAssignment(sfStep.getID());
    }
    workflowRule = assignedUserList.size();
  } else {
    workflowRule = TextUtility.parseInteger(sfStep.getWorkflowRule());
  }
  if(!Utility.isEmpty(navMode)&&navMode.equals(GlobalConstant.NAV_MODE_EDIT)){
    MtmWorkflowProgressUserRecordDAObject mtmProgressUserDAO = new MtmWorkflowProgressUserRecordDAObject(sessionCon, this.getConnection(request));
    List completeUserIDList =  mtmProgressUserDAO.getCompletedUserProcessRecordByWorkflowProgressID(workflowProgress.getID());
    boolean isCompleteUser=false;
    for(int i=0;i<completeUserIDList.size();i++){
      if( sessionCon.getUserRecordID().equals(((MtmWorkflowProgressUserRecord)completeUserIDList.get(i)).getUserRecordID())){
        isCompleteUser=true;
        break;
      }
    }
    if((!(WorkflowProgress.STATUS_PENDING).equals(currentWFprogress.getStatus())
        &&!(WorkflowProgress.STATUS_IN_PROGRESS).equals(currentWFprogress.getStatus()))
        ||(completeUserIDList.size() < workflowRule
            && isCompleteUser)){
      maintForm.setNavMode(GlobalConstant.NAV_MODE_VIEW);
      navMode=GlobalConstant.NAV_MODE_VIEW;
    }
  }
   //end
  log.debug( ((maintForm!=null) ? maintForm.getClass().getName() : "")+", OP Mode:"+opMode+", Nav Mode:"+navMode);
  // get selected decision step
  currentRoute = request.getParameter("workflowRoute");
  if (GlobalConstant.NAV_MODE_VIEW.equals(navMode)) {
    if (Utility.isEmpty(currentRoute)) {
      try {
        //from database get current route
        WorkflowProgessId = Integer.valueOf(request.getParameter("ID"));
        WorkflowStepRouteDAObject stepRouteDAO = new WorkflowStepRouteDAObject(sessionCon, dbConn);
        MtmWorkflowProgressUserRecordDAObject workflowProgessUserRecordDAO=new MtmWorkflowProgressUserRecordDAObject(sessionCon,dbConn);
        MtmWorkflowProgressUserRecord mtmWorkflowProgressUserRecord = workflowProgessUserRecordDAO.getUserRouteObjectByWorkflowProgressIDUserRecordID(WorkflowProgessId, sessionCon.getUserRecordID());
        WorkflowProgressDAObject workflowProgessDAObject = new WorkflowProgressDAObject(sessionCon,dbConn);
        
        WorkflowProgress workflowProgress1 = null;
        workflowProgress1 = (WorkflowProgress)workflowProgessDAObject.getObjectByID(WorkflowProgessId);
        String workflowAction = mtmWorkflowProgressUserRecord.getWorkflowAction();
        //get current step is comment
        if (Utility.isEmpty(currentComment)) {
          currentComment=mtmWorkflowProgressUserRecord.getReason();
        }
        log.debug("workflow step id, getting workflow routes: "+workflowProgress.getWorkflowStepID());
        List tmpList = stepRouteDAO.getListByWorkflowStepID(workflowProgress1.getWorkflowStepID());
        for (int i = 0; i < tmpList.size(); i++) {
          WorkflowStepRoute stepRoute = (WorkflowStepRoute) tmpList.get(i);
          String workflowRouteCur = WorkflowStep.PARENT_TYPE_SINGLE + stepRoute.getRouteSeq();
          if (!Utility.isEmpty(workflowAction)&&workflowAction.equals(workflowRouteCur)) {
            currentRoute = stepRoute.getRouteName();
            break;
          }
          
        }
      }catch(Exception ex){
        log.error(ex, ex);
      }
    }
  } else{     
    WorkflowProgessId = Integer.valueOf(request.getParameter("ID"));
    MtmWorkflowProgressUserRecordDAObject workflowProgessUserRecordDAO=new MtmWorkflowProgressUserRecordDAObject(sessionCon,dbConn);
    MtmWorkflowProgressUserRecord mtmWorkflowProgressUserRecord = workflowProgessUserRecordDAO.getUserRouteObjectByWorkflowProgressIDUserRecordID(WorkflowProgessId, sessionCon.getUserRecordID());
    if (Utility.isEmpty(currentComment)) {
      currentComment=mtmWorkflowProgressUserRecord.getReason();
      maintForm.setReason ( currentComment );
    }
    //simon_add_S
    if (Utility.isEmpty(opMode)||(!Utility.isEmpty(opMode) && !GlobalConstant.OP_MODE_UPDATE.equals(opMode))) {
    	String[] operationParameter=null;
    	operationParameter = new String[1];
    	if (!Utility.isEmpty(mtmWorkflowProgressUserRecord.getOperationParameter())){    	
    		operationParameter[0] = mtmWorkflowProgressUserRecord.getOperationParameter();
    	}else{
    		operationParameter[0]="";	
    	}
    	maintForm.setDecision(operationParameter);
    }
    //simon_add_E
    //display the update message
    this.generateMessage(request);
  }
  request.setAttribute("workflowReason",currentComment);
  request.setAttribute("wrokflowRouteValue",currentRoute);
  
  // Hold the moreStepDueDates value for dynamic assign due date of next steps
  if(!Utility.isEmpty(request.getParameter("moreStepDueDates"))){
    request.setAttribute("moreStepDueDates",request.getParameter("moreStepDueDates"));
  }
  
  // Set the function code for current action.
  ActionForward forward = this.retrieveFunctionCode(request, response, mapping);  if (forward!=null) {return forward;}
  
  // -----------------------------------------------------------------------------------------------
  // Select actors of previous progresses which current user have read permission at.
  
  WorkflowRetrievalManager retrievalManager = new WorkflowRetrievalManager(sessionCon, dbConn);
  WorkflowPermissionManager workflowPermissionManager = new WorkflowPermissionManager(sessionCon, dbConn);
  
  List previousProgressList = retrievalManager.getNonAutomaticParent(currentWFprogress.getID());  // falcon_add
  List progressUserList = new ArrayList();
  for(int j = 0; j < previousProgressList.size(); j++){
    WorkflowProgress previousProgress = (WorkflowProgress)previousProgressList.get(j);
    boolean hasReadRight = workflowPermissionManager.hasAccessRight(null, previousProgress,
        WorkflowPermissionManager.READ_PERMISSION, sessionCon.getUserRecordID());
    if (hasReadRight) {      
      progressUserList.addAll(retrievalManager.getWorkflowProgressUserRecordListByProgressID(previousProgress.getID()));
    }
  }
  request.setAttribute("progressUserList",progressUserList);
  
  
  // Select exist actors of current progress. ------------------------------------------------------
  
  //add by roy for testing end
  List currentProgressUserList = retrievalManager.getWorkflowProgressUserRecordListByProgressID(workflowProgress.getID());
  request.setAttribute("currentProgressUserList",currentProgressUserList);
  
  // Check allow interrupt by current user ---------------------------------------------------------
  if (!Utility.isEmpty(maintForm.getWorkflowRecordID()) && !Utility.isEmpty(maintForm.getWorkflowStepID())) {
    maintForm.setInterruptAble(progressManager.CheckInterruptAble(workflowProgress, new Integer(maintForm.getWorkflowRecordID()))); 
  }
  
  // -----------------------------------------------------------------------------------------------
  // Select all attachments that current user have read permission at.
  
  List progressList = progressManager.getWorkflowProgressList(workflowProgress.getTrackID());
  List attachmentList = new ArrayList();
  for (int i = 0; i < progressList.size(); i++) {
    WorkflowProgress progress = (WorkflowProgress) progressList.get(i);
    boolean hasReadRight = workflowPermissionManager.hasAccessRight(null, progress,
        WorkflowPermissionManager.READ_PERMISSION, sessionCon.getUserRecordID());
    if (hasReadRight) {      
      attachmentList.addAll(progressManager.getWorkflowProgressAttachmentList(progress.getID()));
    }
  }
  request.setAttribute("attachmentList", attachmentList);
  
  
  
  //added by nancy
  maintForm.setAttachmentList(attachmentList);
  List templist=progressManager.getWorkflowProgressAttachmentList(workflowProgress.getID());
  if ((!Utility.isEmpty(opMode) && !GlobalConstant.OP_MODE_UPDATE.equals(opMode))||Utility.isEmpty(opMode)) {
    
    if(!Utility.isEmpty(templist)&&!templist.equals(null)){
      StringBuffer fileNames= new StringBuffer();
      StringBuffer displayFileNames= new StringBuffer();
      StringBuffer dmsFileNames= new StringBuffer();
      StringBuffer displayDmsFileNames= new StringBuffer();
      int j=0;
      int k=0;
      for(int q=0;q<templist.size();q++){
        WorkflowProgressAttachment ff=(WorkflowProgressAttachment)templist.get(q);
        if(ff.getAttachmentType().equals(WorkflowProgressAttachment.ATTACHED_SINGLE_FILE)){
          j=j+1;
          displayFileNames.append(ff.getAttachmentName()+";");
          fileNames.append(ff.getAttachmentName()+":"+ff.getExternalID()+"|");
        }else{
          k=k+1;
          displayDmsFileNames.append(ff.getAttachmentName()+";");
          dmsFileNames.append("["+ff.getExternalID()+"]:["+ff.getAttachmentName()+"]:["+ff.getContentSize()+"];");
          //dmsFileNames.append(ff.getAttachmentName()+":"+ff.getExternalID()+"|");
        }
      }
      
      maintForm.setFileNames((new Integer(j)).toString()+"|"+fileNames.toString());
      maintForm.setDisplayFileNames(displayFileNames.toString());
      //maintForm.setDmsFileNames((new Integer(k)).toString()+"|"+dmsFileNames.toString()); 
      maintForm.setDmsFileNames(dmsFileNames.toString()); 
      maintForm.setDisplayDmsFileNames(displayDmsFileNames.toString());
    }
  }
  //end
  // get reminder records
  MtmWorkflowProgressNotifyRuleDAObject wfProgressNotifyRuleDAO = new MtmWorkflowProgressNotifyRuleDAObject(this.getSessionContainer(request), this.getConnection(request));
  //added by nancy
  WorkflowProgressAttachmentDAObject  wfProgressAttachmentDAO=new WorkflowProgressAttachmentDAObject(this.getSessionContainer(request), this.getConnection(request));
  //end
  List notifyRuleList = wfProgressNotifyRuleDAO.getListByWorkflowProgressID(currentWFprogress.getID(), this.getSessionContainer(request).getUserRecordID());
  request.setAttribute("progressNotifyRuleList", notifyRuleList);
  try {
    if (!Utility.isEmpty(opMode) && GlobalConstant.OP_MODE_UPDATE.equals(opMode)) {
      // Update operation.
      try {
    	//Bill add for EIP-1958 start
        //This workflow record setup DmsAttachmen path when currentRecord.getParentID().intValue()>0  
        if(!Utility.isEmpty(maintForm.getDisplayFileNames()) && 
          SystemWorkflowConstant.DMS_CREATE_PUBLIC_DOCUMENT.equals(tempProgress.getWorkflowCategoryID().toString()) &&
          currentRecord.getParentID().intValue()>0){
          DocumentValidateManager documentValidateManager=new DocumentValidateManager(this.getSessionContainer(request),this.getConnection(request));
          documentValidateManager.checkDmsAttachmentWithPublicFolderSizeByDocumentID(maintForm.getFileNames(), currentRecord.getParentID());
        }
        //Bill add for EIP-1958 end 
    	  
        //added by nancy
        List thisAttachmentList=wfProgressAttachmentDAO.getListByWorkflowProgressID(Integer.valueOf(maintForm.getID()));
        if(!Utility.isEmpty(thisAttachmentList)){
          StringBuffer ss=new StringBuffer();
          for(int k=0;k<thisAttachmentList.size();k++){
            WorkflowProgressAttachment temp=(WorkflowProgressAttachment)thisAttachmentList.get(k);
            ss.append(temp.getMtmWorkflowProgressUserRecordID());
            if(k<thisAttachmentList.size()-1){
              ss.append(",");
            }
          }
          if(ss!=null && !ss.toString().equals("")){
            wfProgressAttachmentDAO.deleteByMtmWorkflowRpogressUserRecordID(ss.toString());
          }
        }


        MtmWorkflowProgressUserRecordDAObject mtmProgressUserDAO = new MtmWorkflowProgressUserRecordDAObject(sessionCon, this.getConnection(request));
        List completeUserIDList =  mtmProgressUserDAO.getCompletedUserProcessRecordByWorkflowProgressID(workflowProgress.getID());
        boolean isCompleteUser=false;
        for(int i=0;i<completeUserIDList.size();i++){
         if( sessionCon.getUserRecordID().equals(((MtmWorkflowProgressUserRecord)completeUserIDList.get(i)).getUserRecordID())){
           isCompleteUser=true;
           break;
         }
        }
        if(!(WorkflowProgress.STATUS_PENDING).equals(currentWFprogress.getStatus())
            &&!(WorkflowProgress.STATUS_IN_PROGRESS).equals(currentWFprogress.getStatus())){
          String completeUserFullName = "";
          for (int j=0; j< completeUserIDList.size(); j++){
            if(j > 0){
              completeUserFullName += ", ";
            }
            completeUserFullName += UserInfoFactory.getUserFullName(((MtmWorkflowProgressUserRecord)completeUserIDList.get(j)).getUserRecordID() );
          }
          if(!Utility.isEmpty(completeUserFullName)){
            addMessage(request,"workflow.message.complete_task",completeUserFullName);
          }
        }else if(completeUserIDList.size() < workflowRule
            && isCompleteUser){
          String completeUserFullName = "";
          for (int j=0; j< completeUserIDList.size(); j++){
            if(j > 0){
              completeUserFullName += ", ";
            }
            completeUserFullName += UserInfoFactory.getUserFullName(((MtmWorkflowProgressUserRecord)completeUserIDList.get(j)).getUserRecordID() );
          }
          if(!Utility.isEmpty(completeUserFullName)){
            addMessage(request,"workflow.message.complete_task",completeUserFullName);
          }
        }else{
          this.updateRecord(mapping, maintForm, request, response);
          this.handleWorkflowRoutine(mapping, maintForm, request, response, opMode, navMode);
          this.commit(request);
//          addMessage(request, MESSAGE_RECORD_UPDATE);
        }
      } catch (ApplicationException appEx) {
        this.rollback(request);
        handleApplicationException(request, appEx);
      }
      if (isError(request)) {
        maintForm.setNavMode(GlobalConstant.NAV_MODE_EDIT);
        return mapping.findForward(GlobalConstant.NAV_MODE_EDIT);
      } else {
        // Handle the next step(s) is CHECKIN auto task Begin
        if( !Utility.isEmpty(maintForm.getCheckInURL()) ){
          try{
            addMessage(request, MESSAGE_RECORD_UPDATE);
            response.sendRedirect(maintForm.getCheckInURL());
            return null;
          } catch(IOException ioex){
            log.error("response send redirect fail!");
          }
        }
        // Handle the next step(s) is CHECKIN auto task End.
        HashMap tmp = (HashMap) request.getAttribute("assignStepMap");
        if (tmp!=null && !tmp.isEmpty()) {
          //log.debug("at TaskAction nav Mode: "+maintForm.getNavMode() + ", op Mode: "+maintForm.getOpMode());
          maintForm.setNavMode(GlobalConstant.NAV_MODE_NEW);
          //log.debug("at TaskAction nav Mode: "+maintForm.getNavMode() + ", op Mode: "+maintForm.getOpMode());
          //======================== store workflow progress status====================================
          String decision[] = maintForm.getDecision();
          if (!Utility.isEmpty(decision) && decision.length > 0){
            request.setAttribute("oldStatus",decision[0]);
          } else {
            request.setAttribute("oldStatus",maintForm.getStatus());
          }
          
          this.addMessage(request, "workflow.message.completed_task_and_assign_owner", maintForm.getStepName());
          return mapping.findForward(WorkflowOperationConstant.WORKFLOW_ASSIGN_USER);
        } else {
          addMessage(request, MESSAGE_RECORD_UPDATE);
          //if Allow user to proceed next task immediately after complete a task and user have next task to do.
          boolean allowProceedNextTask = SystemParameterFactory.getSystemParameterBoolean(SystemParameterConstant.WORKFLOW_ALLOW_TO_PROCEED_NEXT_TASK);
          String nextTaskURL = null;
          if(allowProceedNextTask){
            this.getNextTaskURL(request);
          }
          if( allowProceedNextTask && !Utility.isEmpty(nextTaskURL) ){
            try{                      
              response.sendRedirect(nextTaskURL);
              return null;
            } catch(IOException ioex){
              log.error("response send redirect fail!");
            }
          }             
          maintForm.setNavMode(GlobalConstant.NAV_MODE_VIEW); 
          return mapping.findForward(GlobalConstant.NAV_MODE_VIEW);
        }
      }
      
    } else if (!Utility.isEmpty(navMode) && WorkflowOperationConstant.WORKFLOW_TREE.equals(navMode)) {
      try {
        this.selectRecord(mapping, maintForm, request, response);
      } catch (ApplicationException appEx) {
        handleApplicationException(request, appEx);
      }
      maintForm.setNavMode(GlobalConstant.NAV_MODE_VIEW);
      return mapping.findForward(WorkflowOperationConstant.WORKFLOW_TREE);
    } else if (!Utility.isEmpty(opMode) && WorkflowOperationConstant.OP_MODE_REFESH.equals(opMode)){
    	maintForm.setOpMode(null);
    	try{
    	   	this.selectRecord(mapping, maintForm, request, response);
    	 }catch(Exception appExo){
    	    log.error(appExo,appExo);
    	  }
         return super.execute(mapping, form, request, response);
     }//sliever.hu.add
    else {
      return super.execute(mapping, form, request, response);
    }
  } catch (ApplicationException ex) {
    handleApplicationException(request, ex);
    return mapping.findForward(GlobalConstant.NAV_MODE_LIST);
  }
  }
  
  /**
   * Update the FormSubmission Status
   * @param recordID
   * @param trackID
   * @param status
   * @param sessionContainer
   * @param conn
   */
  public void updateFormSubmission(Integer recordID,
      Integer trackID,
      String status,
      SessionContainer sessionContainer,
      Connection conn) {
    
    try {
      String categoryID = SystemWorkflowConstant.SYS_GENERAL_WORKFLOW;
      WorkflowRecordDAObject recordDAO = new WorkflowRecordDAObject(sessionContainer, conn);
      WorkflowRecord workflowRecord = (WorkflowRecord) recordDAO.getObjectByID(recordID);
      categoryID = workflowRecord.getWorkflowCategoryID().toString();
      MtmWorkflowProgressSystemObjectDAObject progressObjDAO = new  MtmWorkflowProgressSystemObjectDAObject(sessionContainer, conn);
      FormSubmissionDAObject formSubmissionDAO = new FormSubmissionDAObject(sessionContainer,conn);
      
      //update form submission status;
      if (!SystemWorkflowConstant.SYS_GENERAL_WORKFLOW.equals(categoryID)) { //suppose all workflow category, except "general", have other object to combine with
        List objectList = progressObjDAO.getListByTrackID(trackID);
        for (int i=0; i<objectList.size(); i++) {
          MtmWorkflowProgressSystemObject progressObj =
            (MtmWorkflowProgressSystemObject) objectList.get(i);
          Integer formSubmissionID = progressObj.getObjectID();
          
          if (SystemWorkflowConstant.FMB_SUBMISSION_BY_FORM.equals(categoryID)) {
            FormSubmission formSubmission = (FormSubmission) formSubmissionDAO.getObjectByID(formSubmissionID);
            
            //Set the status
            formSubmission.setStatus(status);
            formSubmissionDAO.updateObject(formSubmission);
          }
        }
      }
      
    } catch (Exception e) {
      log.error(e,e);
    }
    
    
  }
  
  
  
  /**
   * operat ProgressMarked
   * @param operateType
   */
  
  public void operatProgressMarked(ActionMapping mapping,
      AbstractActionForm form,
      HttpServletRequest request,
      HttpServletResponse response,String operateType)
  throws ApplicationException {
    SessionContainer sessionContainer = this.getSessionContainer(request);
    
    try {
      //get progressID,workflowStepID
      Integer progressID = new Integer(0);
      Integer workflowStepID = new Integer(0);
      MaintWorkflowProgressForm maintForm = (MaintWorkflowProgressForm) form;
      
      if (!Utility.isEmpty(maintForm.getID() )) {
        progressID = new Integer(maintForm.getID());
      }
      
      if (!Utility.isEmpty(request.getParameter("workflowStepID"))) {
        workflowStepID = new Integer(request.getParameter("workflowStepID"));
      }
      
      
      WorkflowProgressDAObject wfProgressDAO = new WorkflowProgressDAObject(this.getSessionContainer(request), this.getConnection(request));
      WorkflowProgress  wfProgress = (WorkflowProgress)wfProgressDAO.getObjectByID(progressID) ;
      
      WorkflowStepDAObject wfStepDAO = new WorkflowStepDAObject(this.getSessionContainer(request), this.getConnection(request));
      WorkflowStep  wfStep = (WorkflowStep)wfStepDAO.getObjectByID(workflowStepID) ;
      
      
      boolean hasCurrentUserId = true;
      String userId = sessionContainer.getUserRecordID().toString();
      
      
      String[] setSectionIDArray = null;
      if (!Utility.isEmpty(wfProgress.getUserDef5())) {
        StringTokenizer sToken = new StringTokenizer(wfProgress.getUserDef5(), ",");
        setSectionIDArray = new String[sToken.countTokens()];
        for (int i = 0; sToken.hasMoreElements(); i++) {
          String elementValue = (String) sToken.nextElement();
          if(elementValue.equals(userId)) {
            hasCurrentUserId = false;
          }
          setSectionIDArray[i] = elementValue;
        }
      }
      //if current step progressMarked string haven't current user id the throw exception, mean is he have not edit the step
      if (operateType.equals("GET") && !(wfStep.getSectionID().indexOf("0|")==0)){
        if (hasCurrentUserId && !Utility.isEmpty(wfStep.getSectionID()) && !"0|0".equals(wfStep.getSectionID()) && !"0".equals(wfStep.getSectionID()) && Utility.isEmpty(wfProgress.getUserDef4())){
          selectRecord(mapping, form, request, response);
          throw new ApplicationException(ErrorConstant.WORKFLOW_PROCESSOR_NOT_OPERATE_SECTION);
        }
      }
    } catch (ApplicationException appEx) {
      throw appEx;
    } catch (Exception e) {
      log.error(e, e);
      throw new ApplicationException(ErrorConstant.COMMON_FATAL_ERROR, e);
    } finally {}
  }
  
  
  /**
   * get Dms Document Attachment list
   * @param form
   * @return
   */
  private List getDmsDocumentAttachment(AbstractActionForm form){
    MaintWorkflowProgressForm maintForm = (MaintWorkflowProgressForm) form;
    String dmsFileNames = "";
    if(!Utility.isEmpty(maintForm.getDmsFileNames())){
      dmsFileNames = maintForm.getDmsFileNames();
    }
    
    List resultList = new ArrayList();
    WorkflowProgressAttachment attachment = null;
    //String sessionID = sessionCon.getSessionID();
    
    String[] fileNameArray = TextUtility.splitString(dmsFileNames,GlobalConstant.FILENAME_SEPARATOR);
    
    for (int i=0; i<fileNameArray.length; i++) {
      String[] arrName =  TextUtility.splitString(fileNameArray[i],":");
      
      String externalID = arrName[0];
      String fileName = arrName[1];
      String contentSize = arrName[2];
      
      externalID = externalID.substring(1,externalID.length()-1);
      fileName = fileName.substring(1,fileName.length()-1);
      contentSize = contentSize.substring(1,contentSize.length()-1);
      
      attachment = new WorkflowProgressAttachment();
      attachment.setAttachmentName(fileName);
      attachment.setExternalID(externalID);
      attachment.setFlowType(WorkflowProgressAttachment.ATTACHED_SINGLE_FILE);
      //attachment.setDataStream(inputStream);
      attachment.setContentSize(new Integer(contentSize));
      attachment.setAttachmentType(WorkflowProgressAttachment.ATTACHED_DMS_VERSION_SYSTEM_ID);
      resultList.add(attachment);
    }
    
    return resultList;
    
  }
  
  /**
   * check next step(s) is "CHECK IN" auto task
   * e.g.
   *     DMS_Major_Check_In
   *     DMS_No_Update_Check_In
   * @param form
   * @param request
   * @param response
   * @return
   * @throws ApplicationException
   */
  private boolean checkNextStepIsCheckInAutoTask(
      AbstractActionForm form,
      HttpServletRequest request)
  throws ApplicationException {
    MaintWorkflowProgressForm maintForm = (MaintWorkflowProgressForm) form;
    WorkflowProgressDAObject progressDAO = new WorkflowProgressDAObject(this.getSessionContainer(request), this.getConnection(request));
    WorkflowStepDAObject stepDAO = new WorkflowStepDAObject(this.getSessionContainer(request), this.getConnection(request));
    MtmWorkflowStepWorkflowStepDAObject stepStepDAO = new MtmWorkflowStepWorkflowStepDAObject(this.getSessionContainer(request), this.getConnection(request));
    
    WorkflowProgress currentProgress = (WorkflowProgress) maintForm.getFormData();
    
    WorkflowProgress existProgress = (WorkflowProgress) progressDAO.getObjectByID(currentProgress.getID());
    String decision = null;
    if(!Utility.isEmpty(maintForm.getDecision())){
      decision = maintForm.getDecision()[0];
    }
    
    //for decision is the parent type,for approvel and yes/no is the status.
    if(WorkflowStep.ACTION_TYPE_APPROVAL.equals(existProgress.getActionType()) || WorkflowStep.ACTION_TYPE_BOOLEAN.equals(existProgress.getActionType())){
      decision = maintForm.getStatus();
    }
   
    List nextStepList = stepStepDAO.getListByParentStepIDAndParentType(existProgress.getWorkflowStepID(),decision);
    for(int i=0; i<nextStepList.size(); i++){
      MtmWorkflowStepWorkflowStep stepStep = (MtmWorkflowStepWorkflowStep)nextStepList.get(i);
      WorkflowStep tmpStep = (WorkflowStep)stepDAO.getObjectByID(stepStep.getChildStepID());
      if(WorkflowStep.ACTION_TYPE_SYSTEM_AUTO.equals(tmpStep.getActionType())  ){
        
        if(isCheckInAutoTask(SystemWorkflowConstant.DMS_MAJOR_CHECK_IN_AUTO_TASK_IDS, tmpStep.getActionID().toString()) ){
          maintForm.setCheckInType(DmsOperationConstant.CREATE_NEW_CHECKIN);
          return true;
        }
        if(isCheckInAutoTask(SystemWorkflowConstant.DMS_MINOR_CHECK_IN_AUTO_TASK_IDS, tmpStep.getActionID().toString()) ){
          maintForm.setCheckInType(DmsOperationConstant.CREATE_MINOR_CHECKIN);
          return true;
        }
        if(isCheckInAutoTask(SystemWorkflowConstant.DMS_NO_UPDATE_CHECK_IN, tmpStep.getActionID().toString()) ){
          maintForm.setCheckInType(DmsOperationConstant.NO_UPDATE_CHECKIN);
          return true;
        }
      }
    }
    return false;
  }
  
  /**
   * get the check in URL. and check out this document first.
   * @param form
   * @param request
   * @return
   * @throws ApplicationException
   */
  private String getCheckInURL(
      AbstractActionForm form,
      HttpServletRequest request)
  throws ApplicationException {
    String checkInURL = "";
    MaintWorkflowProgressForm maintForm = (MaintWorkflowProgressForm) form;
    MtmWorkflowProgressSystemObjectDAObject sysObjectDAO = new MtmWorkflowProgressSystemObjectDAObject(this.getSessionContainer(request), this.getConnection(request));
    DmsDocumentDAObject dmsDocDAO = new DmsDocumentDAObject(this.getSessionContainer(request), this.getConnection(request));
    
    String trackID = maintForm.getTrackID();
    /**
     * @TODO To get the MtmWorkflowProgressSystemObject by trackID & objectID or other
     */
    MtmWorkflowProgressSystemObject sysObject = null;
    List objectList = sysObjectDAO.getListByTrackID(new Integer(trackID));
    if(!Utility.isEmpty(objectList)){
      sysObject = (MtmWorkflowProgressSystemObject)objectList.get(0);  
    }
    //MtmWorkflowProgressSystemObject sysObject = (MtmWorkflowProgressSystemObject)sysObjectDAO.getObjectByTrackID(new Integer(trackID), dmsD);
    DmsDocument dmsDoc = (DmsDocument)dmsDocDAO.getObjectByID(sysObject.getObjectID());
    
    if(!Utility.isEmpty(dmsDoc)){
      checkInURL = "MaintDmsCheckin.do?" +
      "navMode=E" +
      "&documentID=" + dmsDoc.getID() +
      "&parentID=" + dmsDoc.getParentID() +
      "&rootID=" + dmsDoc.getRootID() +
      "&directURL=MaintWorkflowTrack.do?SHOW_HEADER_FOOTER=" + request.getParameter("SHOW_HEADER_FOOTER") +
      "|showFullList=N|navMode=V" +
      "|trackID=" + maintForm.getTrackID() +
      "|ID="+maintForm.getWorkflowRecordID()+
      "&SHOW_HEADER_FOOTER=" + request.getParameter("SHOW_HEADER_FOOTER") +
      "&checkinType=" + maintForm.getCheckInType();
    }
    log.debug(" Document check in URL::"+checkInURL);
    return checkInURL;
  }
  
  /**
   * check the step if check in auto task.
   * @param checkInActionIDs
   * @param stepActionID
   * @return
   */
  private boolean isCheckInAutoTask(String checkInActionIDs, String stepActionID){
    String[] actionIDArr = TextUtility.splitString(checkInActionIDs,",");
    for(int i=0; i<actionIDArr.length; i++){
      if(actionIDArr[i].equals(stepActionID)){
        return true;
      }
    }
    return false;
  }
  
  /**
   * check the form that must be handel in this task.
   * @param form
   * @param request
   * @throws ApplicationException
   */ 
  
 /* Samlin comment for no use
  *  private boolean checkHandelFormForCurrentTask(
      AbstractActionForm form,
      HttpServletRequest request)
  throws ApplicationException {
    MtmWfProgressAccessFormDAObject accessFormDAO = new MtmWfProgressAccessFormDAObject(this.getSessionContainer(request), this.getConnection(request));
    FormRecordDAObject formRecordDAO = new FormRecordDAObject(this.getSessionContainer(request), this.getConnection(request));
    WorkflowStepDAObject stepDAO = new WorkflowStepDAObject(this.getSessionContainer(request), this.getConnection(request));
    
    boolean hasError = false;
    MaintWorkflowProgressForm maintForm = (MaintWorkflowProgressForm) form;
    String workflowStepID = maintForm.getWorkflowStepID();
    String workflowProgressID = maintForm.getID();
    
    //check the first step pending form submission
    WorkflowStep workflowStep = (WorkflowStep)stepDAO.getObjectByID(new Integer(workflowStepID));
    if( WorkflowStep.ACTION_TYPE_SUBMIT.equals(workflowStep.getActionType()) ){    
      List pendingSubmissionList = formRecordDAO.getPendingSubmitFormListByTrackID(new Integer(maintForm.getTrackID()));
      for(int i=0; i<pendingSubmissionList.size(); i++){
        FormRecord formRecord = (FormRecord)pendingSubmissionList.get(i);
        String errInfo = "[" + formRecord.getFormCode()+ "] " + formRecord.getTitle() + "(" + formRecord.getFormVersion() + ")";
        Object obcect = accessFormDAO.getObjectByWorkflowProgressIDFormRecordIDProcessed(
            new Integer(workflowProgressID), formRecord.getID(), WorkflowStep.FORM_PROCESS_PERMISSION_CHANGE);
        if (Utility.isEmpty(obcect)) {
          // add error;
          addError ( request, WorkflowErrorConstant.MUST_OPERATE_BINDING_FORM, errInfo );
          hasError = true;
        }
      }
    }
    
    //check the form must be operated.
    List operateFormList = formRecordDAO.getOperateFormListByStepID(new Integer(workflowStepID));    
    for(int i=0; i<operateFormList.size(); i++){
      FormRecord formRecord = (FormRecord)operateFormList.get(i);
      String errInfo = "[" + formRecord.getFormCode()+ "] " + formRecord.getTitle() + "(" + formRecord.getFormVersion() + ")";
      Object obcect = accessFormDAO.getObjectByWorkflowProgressIDFormRecordIDProcessed(
          new Integer(workflowProgressID), formRecord.getID(), WorkflowStep.FORM_PROCESS_PERMISSION_CHANGE);
      if (Utility.isEmpty(obcect)) {
        // add error;
        addError ( request, WorkflowErrorConstant.MUST_OPERATE_BINDING_FORM, errInfo );
        hasError = true;
      }
    }
    
    //check the form must be submited.
    List submitFormList = formRecordDAO.getMandatorySubmitFormListByStepID(new Integer(workflowStepID));    
    for(int i=0; i<submitFormList.size(); i++){
      FormRecord formRecord = (FormRecord)submitFormList.get(i);
      String errInfo = "[" + formRecord.getFormCode()+ "] " + formRecord.getTitle() + "(" + formRecord.getFormVersion() + ")";
      
      Object obcect = accessFormDAO.getObjectByWorkflowProgressIDFormRecordIDProcessed(
          new Integer(workflowProgressID), formRecord.getID(), WorkflowStep.FORM_PROCESS_PERMISSION_SUBMIT);
      if (Utility.isEmpty(obcect)) {
        // add error;
        addMessage ( request, WorkflowErrorConstant.MUST_SUBMIT_FORM, errInfo);
        hasError = true;
      }
    }
    
    if(hasError) {
      //throw new ApplicationException(WorkflowErrorConstant.MUST_PROCESS_THESE_BUSINESS);  
    }   
    return hasError;
  }*/
  
  /**
   * Allow user to proceed next task immediately after complete a task.
   * get the next task's URL. 
   * @param request
   * @return
   * @throws ApplicationException
   */ 
  private String getNextTaskURL(
      HttpServletRequest request) throws ApplicationException{
    
    String nextTaskURL = null;
    WorkflowProgressDAObject progressDAO = new WorkflowProgressDAObject(this.getSessionContainer(request), this.getConnection(request));
    
    AbstractSearchForm searchForm = (AbstractSearchForm)request.getSession().getAttribute("workflowTaskList");
    
    // List taskList = progressDAO.getListPendingForUser(searchForm);
    List taskList = progressDAO.getPendingList4UserCanRead(searchForm);
    if( !Utility.isEmpty(taskList)){
      WorkflowProgress progress = (WorkflowProgress)taskList.get(0);
      nextTaskURL = "MaintWorkflowTask.do?" + 
      "SHOW_HEADER_FOOTER=" + ( "N".equals(request.getParameter("SHOW_HEADER_FOOTER"))? "N" : "Y" ) +
      "&navMode=E" +
      "&trackID=" + progress.getTrackID() +
      "&ID=" + progress.getID() + 
      "&workflowRecordID=" + progress.getWorkflowRecordID() + 
      "&oldTrackID=" + request.getParameter("trackID") +
      "&oldProgressID=" + request.getParameter("ID") ;
    }   
    return nextTaskURL;
  }
  
  private void generateMessage(
      HttpServletRequest request) throws ApplicationException{
    String oldTrackID = request.getParameter("oldTrackID");
    String updateMessage = null;
    
    WorkflowProgressDAObject progressDAO = new WorkflowProgressDAObject(this.getSessionContainer(request), this.getConnection(request));
    WorkflowStepDAObject stepDAO = new WorkflowStepDAObject(this.getSessionContainer(request), this.getConnection(request));
    
    if(!Utility.isEmpty(oldTrackID) && !"null".equals(oldTrackID)){
      String oldProgressID = request.getParameter("oldProgressID");
      WorkflowProgress progress = (WorkflowProgress)progressDAO.getObjectByID(new Integer(oldProgressID));
      WorkflowStep step = (WorkflowStep)stepDAO.getObjectByID(progress.getWorkflowStepID());
      updateMessage = MessageResourcesFactory.getMessage(this.getLocale(request), 
          "workflow.message.task_update_successfull", 
          TextUtility.formatNumberWithZeroPrefix(SystemParameterFactory.getSystemParameterInteger(SystemParameterConstant.WORKLFLOW_TRACK_ID_FORMAT_LENGTH).intValue(), new Integer(oldTrackID)), 
          step.getStepName());
      
      request.setAttribute("updateMessage", updateMessage);
    }
    
  }
  
}

